import Sudoku from '../core/sudoku';
import Checker from '../core/checker';

class Grid {

    private _container;

    constructor(container) {
        this._container = container;
    }

    build() {
        const sudoku = new Sudoku();
        sudoku.make();
        const matrix = sudoku.puzzleMatrix;

        const rowGroupClasses = ['row-g-top', 'row-g-middle', 'row-g-bottom'];
        const colGroupClasses = ['col-g-left', 'col-g-center', 'col-g-right'];

        const cells = matrix.map(rowValues => rowValues
            .map((cellValue, colIndex) => {
                return $('<span>')
                    .addClass(colGroupClasses[colIndex % 3])
                    .addClass(cellValue ? 'fixed' : 'empty')
                    .text(cellValue);
            })
        );

        const divArray = cells.map((spanArray, rowIndex) => {
            return $('<div>')
                .addClass('row')
                .addClass(rowGroupClasses[rowIndex % 3])
                .append(spanArray);
        });

        this._container.append(divArray);

        return this;
    }

    layout() {
        const width = <number>$('span:first', this._container).width();

        $('span', this._container)
            .height(width)
            .css({
                'line-height': `${width}px`,
                'font-size': width < 32 ? `${width / 2}px` : ''
            });

        return this;
    }

    bindPopup(popupNumbers) {
        this._container.on('click', 'span', e => {
            const cell = $(e.target);
            if (cell.hasClass('fixed')) {
                return;
            }
            popupNumbers.popup(cell);
        });
    }

    check() {
        const data = this._container.children().map((rowIndex, div) => {
            return $(div).children().map((colIndex, span) => parseInt($(span).text()) || 0);
        }).toArray().map(rowData => rowData.toArray());

        const checker = new Checker(data);
        if (checker.check()) {
            return true;
        }

        const marks = checker.matrixMarks;
        this._container.children()
            .each((rowIndex, div) => {
                $(div).children().each((colIndex, span) => {
                    let _span = $(span);
                    if (_span.hasClass('fixed') || marks[rowIndex][colIndex]) {
                        _span.removeClass('error');
                    } else {
                        _span.addClass('error');
                    }
                })
            });
        return false;
    }

    reset() {
        this._container.find('span:not(.fixed)')
            .removeClass('error mark1 mark2')
            .addClass('empty')
            .text(0);
    }

    clear() {
        this._container.find('span.error')
            .removeClass('error');
    }

    rebuild() {
        this._container.empty();
        this.build();
        this.layout();
    }
}

export {Grid}
export default Grid;
